package main

import (
	"fmt"
	"reflect"
)

func main() {
	chapter_12_2_1()
	chapter_12_2_2()
	chapter_12_2_3()
	chapter_12_2_4()
	chapter_12_2_5()
	chapter_12_2_6()
	chapter_12_2_7()
	chapter_12_3_1()
}

//==================================================================

func chapter_12_2_1() {
	var a int32 = 1
	at := reflect.TypeOf(a)
	if at.Kind() == reflect.Int32 {
		fmt.Println("a type is Int32")
	}
}

//==================================================================

type photoPlayer struct{}

func (o photoPlayer) Start()        {}
func (o photoPlayer) Stop()         {}
func (o photoPlayer) internalStop() {}

func chapter_12_2_2() {
	obj := photoPlayer{}
	objT := reflect.TypeOf(obj)
	methodNum := objT.NumMethod()

	for i := 0; i < methodNum; i++ {
		method := objT.Method(i)
		fmt.Printf("%s, %v\n", method.Name, method.Type)
	}
}

//==================================================================

type test struct {
	m int
	C string
}

func chapter_12_2_3() {
	vx := test{}
	tp := reflect.TypeOf(vx)
	fdNums := tp.NumField()
	for x := 0; x < fdNums; x++ {
		fdMember := tp.Field(x)
		fmt.Printf("字段名称:%s\n", fdMember.Name)
		fmt.Printf("类型:%s\n", fdMember.Type)
		fmt.Printf("程序包路径:%s\n", fdMember.PkgPath)
		fmt.Println()
	}
}

//==================================================================

type address struct {
	Province string
	City     string
	Town     string
	Test     bool
}

type person struct {
	Name string
	Age  uint8
	address
	Test bool
}

type emploee struct {
	person
	Department string
	Code       uint64
	Test       bool
}

func chapter_12_2_4() {
	fmt.Println("chapter_12_2_4")

	var emp emploee
	tp := reflect.TypeOf(emp)

	fdAge, ok := tp.FieldByName("Age")
	if ok {
		fmt.Printf("%s:%v\n", fdAge.Name, fdAge.Index)
	}

	fdCity, ok := tp.FieldByName("City")
	if ok {
		fmt.Printf("%s:%v\n", fdCity.Name, fdCity.Index)
	}

	fdTest, ok := tp.FieldByName("Test")
	if ok {
		fmt.Printf("%s:%v\n", fdTest.Name, fdTest.Index)
	}
}

//==================================================================

func demoFunc(a string, b uint16, c float64) (int32, rune) {
	return 0, 'A'
}

func chapter_12_2_5() {
	fmt.Println("chapter_12_2_5")

	tp := reflect.TypeOf(demoFunc)

	var pNum = tp.NumIn()
	fmt.Println("----函数的输入参数----")
	for x := 0; x < pNum; x++ {
		var p = tp.In(x)
		fmt.Printf("%d: %s\n", x, p.Name())
	}

	var rtNum = tp.NumOut()
	fmt.Println("----函数的返回值----")
	for x := 0; x < rtNum; x++ {
		var r = tp.Out(x)
		fmt.Printf("%d: %s\n", x, r.Name())
	}
}

//==================================================================

func chapter_12_2_6() {
	var (
		C1 chan uint
		C2 chan<- bool
	)

	var t1 = reflect.TypeOf(C1)
	fmt.Println("--C1--")
	fmt.Printf("通道类型:%s\n", t1.Name())
	fmt.Printf("通信方向:")
	switch t1.ChanDir() {
	case reflect.RecvDir:
		fmt.Println("只能从通道接收数据")
	case reflect.SendDir:
		fmt.Println("只能从通道发送数据")
	case reflect.BothDir:
		fmt.Println("同时支持发送和接收数据")
	}

	var t2 = reflect.TypeOf(C2)
	fmt.Println("--C2--")

	fmt.Printf("通道类型:%s\n", t2.Name())
	fmt.Printf("通信方向:")
	switch t2.ChanDir() {
	case reflect.RecvDir:
		fmt.Println("只能从通道接收数据")
	case reflect.SendDir:
		fmt.Println("只能从通道发送数据")
	case reflect.BothDir:
		fmt.Println("同时支持发送和接收数据")
	}
}

//==================================================================

type ball interface {
	Play()
}

type gymnastics interface {
	Do()
}

type footBall struct{}

func (b footBall) Play() {
	fmt.Println("踢足球")
}

func chapter_12_2_7() {
	fmt.Println("chapter_12_2_7")

	var tpOfBall = reflect.TypeOf(new(ball)).Elem()
	var tpOfGy = reflect.TypeOf(new(gymnastics)).Elem()

	var tpOfFb = reflect.TypeOf(footBall{})

	var b1 = tpOfFb.Implements(tpOfBall)
	fmt.Printf("结构体 %s ", tpOfFb.Name())
	if b1 {
		fmt.Print("实现了")
	} else {
		fmt.Print("未实现")
	}
	fmt.Printf("%s接口\n", tpOfBall.Name())

	var b2 = tpOfFb.Implements(tpOfGy)
	fmt.Printf("结构体 %s ", tpOfFb.Name())
	if b2 {
		fmt.Print("实现了")
	} else {
		fmt.Print("未实现")
	}
	fmt.Printf("%s接口\n", tpOfGy.Name())
}

//==================================================================

func chapter_12_3_1() {
	fmt.Println("chapter_12_3_1")

	var who string = "小明"
	fmt.Printf("变量who的原值:%v\n", who)

	// 通过反射技术修改变量的值
	var val = reflect.ValueOf(&who)
	// 获取指针指向的对象
	val = val.Elem()
	if val.Kind() == reflect.String {
		val.Set(reflect.ValueOf("小吴"))
	} else {
		fmt.Println("变量who不允许被修改")
	}

	//var bv = false
	//fmt.Printf("变量的原值:%v\n", bv)
	//
	//var val2 = reflect.TypeOf(&bv)
	//var blVal = val2.Elem()
	//if blVal.Kind() == reflect.Bool && blVal.CanSet() {
	//	blVal.SetBool(true)
	//}
}

//==================================================================

func chapter_12_3_2() {

}
